/**
  ******************************************************************************
  * @file    fsm_event_queue.c
  * @author  ashuai0110
  * @version V2.4
  * @date    2024-09-10
  * @brief   有限状态机的事件队列
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者(ashuai0110)原创,使用请注明出处,当然,你也可以不这样做^_^
  * 出处链接:https://gitee.com/ashuai0110/mcu_reuse_development_module.git
  *
  * Change Logs:
  * Date          Author        Notes
  * 2024-08-15    ashuai0110    完成基本内容
  * 2024-08-16    ashuai0110    优化读写逻辑,读写时增加临界区控制
  *
  ******************************************************************************
  */

/* 包含头文件-----------------------------------------------------------------*/
#include "fsm_event_queue.h"

/**
 * @addtogroup state_machine
 * @{
 */

/**
 * @defgroup fsm_event_queue fsm_event_queue
 * @{
 */

/* 私有宏定义-----------------------------------------------------------------*/
/**
 * @defgroup fsm_event_queue_local_macros fsm event queue local macros
 * @{
 */

/**
 * @defgroup fsm_event_queue_check_parameters_validity fsm event queue check parameters validity
 * @{
 */
/* 事件队列缓冲区大小有效性检查 */
#define IS_VALID_EVENT_BUF_LEN(x)                                             \
(       (x) != 0u)
/**
 * @}
 */

/**
 * @}
 */

/* 私有类型定义---------------------------------------------------------------*/

/* 私有变量-------------------------------------------------------------------*/

/* 全局变量-------------------------------------------------------------------*/

/* 私有函数原型---------------------------------------------------------------*/

/**
 * @defgroup fsm_event_queue_global_functions fsm event queue global functions
 * @{
 */

/**
  * @brief  FSM事件队列初始化
  *
  * @note   应在fsm_init()之前执行
  *
  * @param  _fsmEq : FSM事件队列实例化对象
  *
  * @param  buf    : 队列缓冲区
  *
  * @param  bufLen : 缓冲区长度byte
  *
  * @retval None
  */
void fsm_eq_init(fsm_eq_t *_fsmEq, void *buf, uint32_t bufLen)
{
    MW_ASSERT_PARAM(IS_VALID_POINTER(_fsmEq));
    MW_ASSERT_PARAM(IS_VALID_POINTER(buf));
    MW_ASSERT_PARAM(IS_VALID_EVENT_BUF_LEN(bufLen));

    /* 初始化各参数 */
    memset(_fsmEq, 0, sizeof(fsm_eq_t));
    _fsmEq->eventBuf = (char *)buf;
    _fsmEq->bufLen = bufLen;
}

/**
  * @brief  FSM事件队列读取
  *
  * @param  _fsmEq  : FSM事件队列实例化对象
  *
  * @param  event   : FSM事件
  *
  * @param  rdLen   : 读取长度byte
  *
  * @retval 返回读取状态
  *    @arg MW_RET_OK  : 读取成功
  *    @arg MW_RET_ERR : 读取失败
  */
uint8_t fsm_eq_read(fsm_eq_t *_fsmEq, fsm_event_t *event, uint32_t rdLen)
{
    /* 可读长度小于需读取长度则返回读取失败 */
    if((_fsmEq->wrIndex == _fsmEq->rdIndex) && !_fsmEq->rwFlag)
    {
        return MW_RET_ERR;
    }

    MW_CRITICAL_LOCK();
    /* 依据读索引从缓冲区读取至需读取数据 */
    memcpy((void *)event, &_fsmEq->eventBuf[_fsmEq->rdIndex], rdLen);
    _fsmEq->rdIndex += rdLen;
    /* 如果读索引已满则归零 */
    if(_fsmEq->rdIndex == _fsmEq->bufLen)
    {
        _fsmEq->rdIndex = 0;
    }
    _fsmEq->rwFlag = 0;
    MW_CRITICAL_UNLOCK();

    return MW_RET_OK;
}

/**
  * @brief  FSM事件队列写入
  *
  * @param  _fsmEq  : FSM事件队列实例化对象
  *
  * @param  event   : FSM事件
  *
  * @param  rdLen   : 写入长度byte
  *
  * @retval 返回写入状态
  *    @arg MW_RET_OK  : 写入成功
  *    @arg MW_RET_ERR : 写入失败
  */
uint8_t fsm_eq_write(fsm_eq_t *_fsmEq, fsm_event_t *event, uint32_t wrLen)
{
    /* 可写长度小于需写入长度则返回写入失败 */
    if((_fsmEq->wrIndex == _fsmEq->rdIndex) && _fsmEq->rwFlag)
    {
        return MW_RET_ERR;
    }

    MW_CRITICAL_LOCK();
    /* 依据写索引将需写入数据写入缓冲区 */
    memcpy(&_fsmEq->eventBuf[_fsmEq->wrIndex], (void *)event, wrLen);
    _fsmEq->wrIndex += wrLen;
    /* 如果写索引已满则归零 */
    if(_fsmEq->wrIndex == _fsmEq->bufLen)
    {
        _fsmEq->wrIndex = 0;
    }
    _fsmEq->rwFlag = 1;
    MW_CRITICAL_UNLOCK();

    return MW_RET_OK;
}

/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */
